﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

namespace AuthenticationDemo.Middleware
{
    public class FallbackAuthenticationMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IAuthenticationSchemeProvider _schemeProvider;

        public FallbackAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemeProvider)
        {
            _next = next;
            _schemeProvider = schemeProvider;
        }
        /// <summary>
        /// 身份认证方案
        /// 默认JW。JWT失败，执行自定义认证
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context)
        {
            var endpoints = context.GetEndpoint();
            if (endpoints == null || !endpoints.Metadata.OfType<IAuthorizeData>().Any() || endpoints.Metadata.OfType<IAllowAnonymous>().Any())
            {
                await _next(context);
                return;
            }

            //默认JW。JWT失败，执行自定义认证
            var result = await Authenticate_JwtAsync(context);
            if (!result.Succeeded)
                result = await Authenticate_CustomTokenAsync(context);

            // 设置认证票据到HttpContext中 
            if (result.Succeeded)
                context.User = result.Principal;

            await _next(context);
        }
        /// <summary>
        /// Jwt的认证
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task<dynamic> Authenticate_JwtAsync(HttpContext context)
        {
            var verify = context.User?.Identity?.IsAuthenticated ?? false;
            string authenticationType = context.User.Identity.AuthenticationType;
            if (verify && authenticationType != null)
            {
                return new { Succeeded = verify, Principal = context.User, Message = "" };
            }

            await Task.CompletedTask;

            // 找不到JWT身份验证方案，或者无法获取处理程序。
            return new { Succeeded = false, Principal = new ClaimsPrincipal { }, Message = "JWT authentication scheme not found or handler could not be obtained." };
        }

        /// <summary>
        /// 自定义认证
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private async Task<dynamic> Authenticate_CustomTokenAsync(HttpContext context)
        {
            // 自定义认证方案的名称
            var customScheme = "CustomAuthenticationHandler";

            var fixedTokenHandler = await context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>().GetHandlerAsync(context, customScheme);
            if (fixedTokenHandler != null)
            {
                var Res = await fixedTokenHandler.AuthenticateAsync();
                return new { Res.Succeeded, Res.Principal, Res.Failure?.Message };
            }

            //找不到CustomAuthenticationHandler身份验证方案，或者无法获取处理程序。
            return new { Succeeded = false, Principal = new ClaimsPrincipal { }, Message = "CustomAuthenticationHandler authentication scheme not found or handler could not be obtained." };

        }
    }
}
